

/**
 * 设置cookie
 * @param {String} key cookie的名字
 * @param {String} value cookie的值
 * @param {Number} expires 传递过期时间，单位为秒 默认值0表示关闭浏览器失效
 */

function setCookie(key, value, expires = 0) {
    if (expires == 0) {
        // path=/  cookie路径  整个域名都可以使用
        document.cookie = `${key}=${value};path=/`
    } else {
        let d = new Date();
        //设置的是格林威治时间需要减8小时
        d.setTime(d.getTime() - 8 * 3600 * 1000 + expires * 1000)
        document.cookie = `${key}=${value};path=/;expires=${d}`;
    }
}

/**
 * 删除cookie
 * @param {String} key cookie的名字 
 */
function removeCookie(key) {
    setCookie(key, '', -1);
}

/**
 * 获取cookie的值
 * @param String key cookie的名字
 * @returns 
 */
function getCookie(key) {
    let value = '';

    document.cookie.split('; ').forEach(item => {
        let keyValue = item.split('=')
        if (key == keyValue[0]) {
            value = keyValue[1]
        }
    })
    return value;
}


/**
 * 发送ajax请求
 * @param {Object} options 发送请求参数
 */
function ajax(options) {
    // console.log(options)
    // 1.默认配置信息
    let config = {
        url: '', //请求地址
        type: 'get', //请求方式
        data: '',    //请求额外携带的参数，可以是字符串/对象
        contentType: 'application/x-www-form-urlencoded', //设置请求头content-type对应的值
        dataType: 'json',    //服务端默认返回的数据 格式
        success: function () { }
    }
    //2.默认配置的合并
    for (let key in config) {
        //检查options中是否有传递对应key值的属性，如果存在 就覆盖
        options[key] && (config[key] = options[key]);
    }
    // console.log(config)

    // 3.检查每一个参数是否满足要求
    // 3-1验证url考虑可能存在前端与后端在同一个目录下 可以省略http之类。所以url只限制必须传递
    if (!config.url) throw new Error("url必须传递!")
    // 3-2、验证请求方式
    //存储容许的请求方式
    let allowType = ['get', 'post', 'put', 'delete'];
    //将请求转化为小写
    config.type = config.type.toLowerCase();
    if (!allowType.includes(config.type)) {
        throw new Error('请求方式设置错误');
    }
    //3-3验证请求数据 要求请求数据格式只能是字符串/对象
    let dataType = Object.prototype.toString.call(config.data);
    if (dataType != '[object String]' && dataType != '[object Object]') {
        throw new Error('请求数据格式错误')
    }
    //3-4验证回调 要求必须是函数
    if (Object.prototype.toString.call(config.success) != '[object Function]')
    {
        console.log(Object.prototype.toString.call(config.success));
        throw new Error('回调必须是一个函数');
    }
    //4、构建请求携带的数据 config.data 可能是字符串 也可能是对象，如果是字符串 什么事情都不做处理否则需要将对象转换为字符串
    let data = '';//保存请求携带的数据
    if(Object.prototype.toString.call(config.data) =='[object String]'){
        data = config.data;
    } else{
        //如果是get，delete请求 字符串最终需要放到URL地址上 格式是key/value格式；如果是post，put请求 格式是key/value或者JSON格式
        if((config.type == 'post'||config == 'put')&&config.contentType == 'application/json'){
            // 设置请求参数为JSON格式
            data = JSON.stringify(config.data);
        }else{
            //循环做字符串的拼接 &
            for(let key in config.data){
                data +=`${key}=${config.data[key]}&`
            }
            //截取最后多的一个 &
            data = data.substring(0,data.length-1);
        }
    }
    //5获取Ajax对象
    let xhr = new XMLHttpRequest;
    // 6.打开链接
    //保存请求地址
    let url = config.url;
    if((config.type == 'get' || config.type == 'delete') &&data) url = config.url +'?'+data;
    xhr.open(config.type,url);
    // 设置请求头信息
    xhr.setRequestHeader('Content-type',config.contentType);
    // 7.发送请求
    //判断请求方式为post/put 并且data中参数需要携带 所以才使用data 否则就传 空
    xhr.send(((config.type == 'post' ||config.type =='put') && data)?data:'');
    // console.log(data);
    // xhr.send(data)
    // 8.监听状态的改变
    xhr.onreadystatechange = function (){
        if(xhr.status == 200 && xhr.readyState == 4){
            let response = (config.dataType == 'json')?JSON.parse(xhr.responseText):xhr.responseText;
            //使用回调函数处理结果
            config.success(response)
        }
    }
}

/**
 * promise版本的Ajax   
 * @param {Object} options 发送请求参数 参数整体与ajax函数的参数类似，只有success是不需要传递 
 */
 function pajax(options){
    // 因为每次使用Ajax想要使用promise必须手动new 所以将手动new的操作放到函数中
    return new Promise(function(resolve,reject){
        // 成功的回调。一旦ajax函数拿到结果会自动调用这个函数
        options.success = function(response){
            // 调用then方法中第一个匿名函数
            resolve(response)
        }

        // 实现具体异步的代码 异步要做的就是发送请求。所以直接调用已有的ajax函数完成请求的发送
        // 由于请求的地址、参数、等信息不确定 所以在调用ajax函数时传递的信息需要由调用pajax函数来进行传递
        ajax(options);
    })
}




/**
 * 从URL地址中获取指定名称的参数
 * @param {String} key 要获取参数的名称
 * @returns 
 */
 function getUrlParam(key){
    var result;
    // 截取字符串
    location.search.substr(1).split('&').forEach(function(item){
        // console.log(item)
        var keyValue = item.split('=');
        if(keyValue[0] == key){
            result = keyValue[1];
        }
    })
    return result;
}


